6. 極方程式#

6.1. 配付資料#

Hide code cell source
# おまじない。1度実行しましょう。
!pip install japanize-matplotlib
Hide code cell output
Collecting japanize-matplotlib
  Downloading japanize-matplotlib-1.1.3.tar.gz (4.1 MB)
?25l     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/4.1 MB ? eta -:--:--
     ━━━━━━━━━━╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.1/4.1 MB 31.6 MB/s eta 0:00:01
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━╺━━━━━━━━━━━━ 2.8/4.1 MB 40.9 MB/s eta 0:00:01
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸ 4.1/4.1 MB 37.9 MB/s eta 0:00:01
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸ 4.1/4.1 MB 37.9 MB/s eta 0:00:01
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.1/4.1 MB 26.5 MB/s eta 0:00:00
?25h  Preparing metadata (setup.py) ... ?25l?25hdone
Requirement already satisfied: matplotlib in /usr/local/lib/python3.11/dist-packages (from japanize-matplotlib) (3.10.0)
Requirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.11/dist-packages (from matplotlib->japanize-matplotlib) (1.3.1)
Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.11/dist-packages (from matplotlib->japanize-matplotlib) (0.12.1)
Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.11/dist-packages (from matplotlib->japanize-matplotlib) (4.55.3)
Requirement already satisfied: kiwisolver>=1.3.1 in /usr/local/lib/python3.11/dist-packages (from matplotlib->japanize-matplotlib) (1.4.8)
Requirement already satisfied: numpy>=1.23 in /usr/local/lib/python3.11/dist-packages (from matplotlib->japanize-matplotlib) (1.26.4)
Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.11/dist-packages (from matplotlib->japanize-matplotlib) (24.2)
Requirement already satisfied: pillow>=8 in /usr/local/lib/python3.11/dist-packages (from matplotlib->japanize-matplotlib) (11.1.0)
Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.11/dist-packages (from matplotlib->japanize-matplotlib) (3.2.1)
Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.11/dist-packages (from matplotlib->japanize-matplotlib) (2.8.2)
Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.11/dist-packages (from python-dateutil>=2.7->matplotlib->japanize-matplotlib) (1.17.0)
Building wheels for collected packages: japanize-matplotlib
  Building wheel for japanize-matplotlib (setup.py) ... ?25l?25hdone
  Created wheel for japanize-matplotlib: filename=japanize_matplotlib-1.1.3-py3-none-any.whl size=4120257 sha256=8b875552381d5b0f65b479a60e6508d44f4f22b44d0eba86d391d787cd236b03
  Stored in directory: /root/.cache/pip/wheels/da/a1/71/b8faeb93276fed10edffcca20746f1ef6f8d9e071eee8425fc
Successfully built japanize-matplotlib
Installing collected packages: japanize-matplotlib
Successfully installed japanize-matplotlib-1.1.3
Hide code cell source
# おまじない。1度実行しましょう
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.collections
import matplotlib.animation
import matplotlib.colors
import japanize_matplotlib
import math
from IPython.display import HTML

# おまじないその2
## 曲座標→デカルト座標
def coordinate(r, theta):
  x = r * np.cos(theta)
  y = r * np.sin(theta)
  return x, y

def draw_step(ax, r, theta):
    artist = []
    x, y = coordinate(r, theta)
    artist.extend(ax.plot(x, y, 'ro'))
    artist.extend(ax.plot([0, x], [0, y], color='blue', linestyle='--'))
    artist.append(ax.text(x, y, r"$r = {:.2f}$".format(r) + "\n"+ r"$\theta = {:.2f}$".format(theta), ha='right'))
    return artist

def draw_steps(ax, artist_prev, r, theta):
    artist = []
    x, y = coordinate(r, theta)
    artist_prev.extend(ax.plot(x, y, 'ro'))
    artist.extend(artist_prev)
    artist.extend(ax.plot([0, x], [0, y], color='blue', linestyle='--'))
    artist.append(ax.text(x, y, r"$r = {:.2f}$".format(abs(r)) + "\n"+ r"$\theta = {:.2f}$".format(theta), ha='right'))
    return artist

def draw_finish(ax, artist_prev, X, Y, pole = '極'):
  ax.plot(0,0, 'o', color = 'b')
  ax.text(0,0.01, pole)
  ax.set_xlabel('$x$')
  ax.set_ylabel('$y$')
  ax.grid()

  artist = []
  artist.extend(artist_prev)
  artist.extend(ax.plot(X, Y, color='blue'))
  return artist

7. 極方程式#

今までは、直交座標系と呼ばれる、いわゆる\(x\)軸と\(y\)軸からなる座標系で考えてきましたが、それ以外にも

  • 原点からの距離\(r\)

  • \(x\)軸正の方向から測った角度\(\theta\)

で記述できました。これを用いて、座標平面上の点を\((r, \theta)\)と表したものを極座標と呼びました。

これは複素数でみた極形式が、複素数平面上(\(\mathbb{C}\))のある点を

  • 原点からの距離\(r\)

  • 実軸の正の方向となす角\(\theta\)

で表せたのと同じですよね。

さらに、座標平面上の曲線が、\(x,y\)の方程式で表すころができたように、極座標を用いても同様に表現できます。それが極方程式になります。

定義/極方程式

平面上の曲線\(C\)が極座標\((r, \theta)\)によって、

  • \(r=f(\theta)\)

  • \(F(r,\theta)=0\) (\(r\)\(\theta\)の式\(= 0\))

のいずれかで書かれるとき、この方程式を曲線\(C\)極方程式という。

では実際の例を見てみましょう。

極方程式では、

  • 図形のイメージを掴む

  • 複数の点をプロットすることによって概形を描けるようになる

ことが習得の鍵になるでしょう。

7.1. アルキメデスの螺旋#

極方程式

(7.1)#\[\begin{equation} r = \theta \end{equation}\]

で表される曲線はアルキメデスの螺旋です。以下の図は\(0\leqq \theta \leqq 6\pi\)で描いています。

Hide code cell source
# αの値
alpha = 1
# 描画の細かさ
stp = 0.3

stp_line = 0.00001
max_range = 6 * np.pi
theta = np.arange(0, max_range, stp_line)
thetas = np.arange(0, max_range, stp)
def f(x):
  return alpha * x

# base figure
X,Y = coordinate(f(theta), theta)
fig, ax = plt.subplots()

# animation drawing section
artists = []
artist_prev = []
for t in thetas:
  artists.append(draw_steps(ax,artist_prev, f(t), t))

artists.append(draw_finish(ax, artist_prev, X, Y))

ani = matplotlib.animation.ArtistAnimation(fig, artists, interval=300)
html = ani.to_jshtml(default_mode = 'once')
plt.close(fig)
ani.save('archimedes.mp4')
HTML(html)

解説.

アルキメデスの螺旋は一般に

(7.2)#\[\begin{equation} r = \alpha \theta \: (\alpha \text{はパラメータ}) \end{equation}\]

と表すことができます。

check

上の図において極方程式の\(\alpha\)の値を変更して、図形がどのように変化するだろうか。

7.2. カージオイド#

極方程式

(7.3)#\[\begin{equation} r=1 + \cos \theta \end{equation}\]

カージオイドを表します。以下の図はこの極方程式を\(0\leqq \theta \leqq 2\pi\)で描いたものです。

Hide code cell source
a = 1
# ±のうち+なら1, -なら0
is_positive = 1
# 上の式のcosの方なら1, sinの方なら0
is_cos = 1
# 描画の細かさ
stp = 0.2

stp_line = 0.00001
max_range = 2 * np.pi
theta = np.arange(0, max_range, stp_line)
thetas = np.arange(0, max_range, stp)
def f(x):
  return a * (1 + (np.cos(x) if is_cos else np.sin(x))) * (1 if is_positive else -1)

# base figure
X,Y = coordinate(f(theta), theta)
fig, ax = plt.subplots()

# animation drawing section
artists = []
artist_prev = []
for t in thetas:
  artists.append(draw_steps(ax,artist_prev, f(t), t))

artists.append(draw_finish(ax, artist_prev, X, Y))

ani = matplotlib.animation.ArtistAnimation(fig, artists, interval=450)
html = ani.to_jshtml(default_mode = 'once')
plt.close(fig)
ani.save('cardioid.mp4')
HTML(html)

解説.

カージオイドの極方程式は一般には

(7.4)#\[\begin{equation} r=a(1\pm \cos \theta) \quad {または} \quad r=a(1\pm \sin \theta) \end{equation}\]

と表されます。ここで\(a\)はパラメータで、自由に設定できます。概形を見てみたい人はこのページ\(a\)を変化させてみましょう。

7.3. 正葉曲線#

極方程式

\[\begin{equation*} r = \sin 2\theta \end{equation*}\]

で表される曲線は正葉曲線です。以下の図はこの極方程式を\(0\leqq \theta \leqq 2\pi\)で描いたものです。

演習問題1も、正葉曲線です。

Hide code cell source
# 各値の指定
a = 1
n = 2
# r = a cos nθにするかどうかの指定。is_cos = 1ならr = a cos nθになる。
is_cos = 0
# アニメーションの細かさ
stp = 0.2

stp_line = 0.00001
theta = np.arange(0, 2 * np.pi, stp_line)
thetas = np.arange(0, 2 * np.pi, stp)
def f(x):
  return a * (np.cos(n*x) if is_cos else np.sin(n * x))

# base figure
X,Y = coordinate(f(theta), theta)
fig, ax = plt.subplots()

# animation drawing section
artists = []
artist_prev = []
for t in thetas:
  artists.append(draw_steps(ax,artist_prev, f(t), t))

artists.append(draw_finish(ax, artist_prev, X, Y))

ani = matplotlib.animation.ArtistAnimation(fig, artists, interval=500)
html = ani.to_jshtml(default_mode = 'once')
plt.close(fig)
ani.save('rose.mp4')
HTML(html)

7.4. リマソン(パスカルの蝸牛)#

極方程式

(7.5)#\[\begin{equation} r = 1 + 2 \cos \theta \end{equation}\]

で表される曲線をリマソンまたはパスカルの蝸牛といいます。蝸牛というのは我々の耳の中にある感覚器官「渦巻管」のことです。

Hide code cell source
# 各値の指定
a = 1
b = 2

# アニメーションの細かさ
stp = 0.2

stp_line = 0.00001
theta = np.arange(0, 2 * np.pi, stp_line)
thetas = np.arange(0, 2 * np.pi, stp)
def f(x):
  return a + b * np.cos(x)

# base figure
X,Y = coordinate(f(theta), theta)
fig, ax = plt.subplots()

# animation drawing section
artists = []
artist_prev = []
for t in thetas:
  artists.append(draw_steps(ax,artist_prev, f(t), t))

artists.append(draw_finish(ax, artist_prev, X, Y))

ani = matplotlib.animation.ArtistAnimation(fig, artists, interval=500)
html = ani.to_jshtml(default_mode = 'once')
plt.close(fig)
HTML(html)

解説.

リマソンは一般に

(7.6)#\[\begin{equation} r = a + b \cos \theta \end{equation}\]

で表されます。\(a,b\)が変化すると曲線が変わっていきます。

Tip

カージオイドとの関係はどうなっているでしょうか。式の形がにていませんか?

8. 演習問題#

では、極方程式が与えられた時に、どのような図形になるか、実際に自分の手で描いてみましょう。

8.1. 手順#

  • A問題とB問題をペアで分担。解けたらお互いに説明し合ってみよう。

  • 例題と似た曲線なので、困ったら例題のアニメーションを参考にしよう。

  • A問題とB問題で描いた曲線を比較・考察しよう。その際には以下の観点などを使うとよい。

    • 二つの図を比較して、パラメータにはどのような関係がある?

    • 楽に描く工夫で思いつくものはある?

    • もし、この曲線を𝑥,𝑦の方程式で表そうとするとどの様な感じになりそう?

8.2. 演習1#

8.2.1. 演習A.1#

極方程式

\[\begin{equation*} r = \sin 3\theta \: (0\leqq \theta \leqq 2\pi) \end{equation*}\]

が表す曲線の概形を図示せよ。

8.2.2. 演習B.1#

極方程式

\[\begin{equation*} r = \sin 4\theta \: (0\leqq \theta \leqq 2\pi) \end{equation*}\]

が表す曲線の概形を図示せよ。

Hint

まずは具体的な点の座標を計算してみよう。

\(\theta\)

\(0\)

\(\frac{\pi}{6}\)

\(\frac{\pi}{4}\)

\(\frac{\pi}{3}\)

\(\frac{\pi}{2}\)

\(\frac{2\pi}{3}\)

\(\frac{3\pi}{4}\)

\(\frac{5\pi}{6}\)

\(\pi\)

\(\frac{7\pi}{6}\)

\(\frac{5\pi}{4}\)

\(\frac{4\pi}{3}\)

\(\frac{3\pi}{2}\)

\(\frac{5\pi}{3}\)

\(\frac{7\pi}{4}\)

\(\frac{11\pi}{6}\)

\(r\)

   |              |               |                  |                  | 

Hint

正葉曲線を参考にしよう。

8.3. 演習2#

8.3.1. 演習A.2#

極方程式

\[\begin{equation*} r = 1+2\sin \theta \: (0\leqq \theta \leqq 2\pi) \end{equation*}\]

が表す曲線の概形を図示せよ。

8.3.2. 演習B.2#

極方程式

\[\begin{equation*} r = 1-5\cos \theta \: (0\leqq \theta \leqq 2\pi) \end{equation*}\]

が表す曲線の概形を図示せよ。

Hint

リマソン(パスカルの蝸牛)を参考にしよう。

8.4. 演習問題解答#

演習解答ページを参照。

8.5. 発展問題#

余裕のある人は取り組んでみてください。

8.5.1. 発展問題A#

極方程式

\[\begin{equation*} r = \frac{1}{\theta} \end{equation*}\]

によって表される曲線を描きなさい。

Hint

アルキメデスの螺旋を参考にすると良い。

Hide code cell source
a = 1
# 描画の細かさ
stp = 0.2


p = 1
# drawing range settings
min_range = np.pi / 3 if p > 0 else 0
max_range = 8 * np.pi if p > 0 else 6 * np.pi

stp_line = 0.00001
theta = np.arange(min_range, 2 * max_range, stp_line)
thetas = np.arange(min_range, max_range, stp)
def f(x):
  # to prevent from dividing with 0
  return a / (x ** p) if p > 0 else a * (x ** abs(p))

# base figure
X,Y = coordinate(f(theta), theta)
fig, ax = plt.subplots()

# animation drawing section
artists = []
artist_prev = []
for t in thetas:
  artists.append(draw_steps(ax,artist_prev, f(t), t))

artists.append(draw_finish(ax, artist_prev, X, Y))

ani = matplotlib.animation.ArtistAnimation(fig, artists, interval=250)
html = ani.to_jshtml(default_mode = 'once')
plt.close(fig)
# ani.save('hyp_cycle.gif')
ani.save('anim.mp4', writer="ffmpeg")
HTML(html)
Hide code cell output

解説.

極方程式

\[\begin{equation*} r = \frac{a}{\theta} \end{equation*}\]

によって表される曲線を は双曲螺旋です。ここで重要なのは、\(\theta\)が小さい方から徐々に大きくなる時の、点の動きです。点は螺旋の外から内に向かって進みます。

逆に、\(\theta\)が分子に来るものはアルキメデスの螺旋でした。アルキメデスの螺旋では、\(\theta\)が大きくなるにつれて\(r\)は小さくなりました。この双曲螺旋では逆に、\(\theta\)が大きくなると\(r\)は小さくなります。

  • アルキメデスの螺旋\(\to\) \(\theta\)が大きくなると、\(r\)も大きくなる\(\Rightarrow\)内から外へ巻く

  • 双曲螺旋\(\to\) \(\theta\)が大きくなると\(r\)は小さくなる\(\Rightarrow\)外から内へ巻く

8.5.2. 発展問題B#

極方程式

\[\begin{equation*} r = \frac{1}{\sqrt{\theta}} \end{equation*}\]

によって表される曲線を描きなさい。

Hide code cell source
a = 1
p = -1
# 描画の細かさ
stp = 0.2


# drawing range settings
min_range = np.pi / 3 if p > 0 else 0
max_range = 8 * np.pi if p > 0 else 6 * np.pi

stp_line = 0.00001
theta = np.arange(min_range, max_range, stp_line)
thetas = np.arange(min_range, max_range, stp)
def f(x):
  # to prevent from dividing with 0
  return a / (x ** p) if p > 0 else a * (x ** abs(p))

# base figure
X,Y = coordinate(f(theta), theta)
fig, ax = plt.subplots()

# animation drawing section
artists = []
artist_prev = []
for t in thetas:
  artists.append(draw_steps(ax,artist_prev, f(t), t))

artists.append(draw_finish(ax, artist_prev, X, Y))

ani = matplotlib.animation.ArtistAnimation(fig, artists, interval=500)
html = ani.to_jshtml(default_mode = 'once')
plt.close(fig)
HTML(html)
Hide code cell output

解説.

極方程式

\[\begin{equation*} r = \frac{a}{\sqrt{\theta}} \end{equation*}\]

この極方程式で表される曲線はリチュースと呼ばれます。 これは先ほど見た双曲螺旋の分母に\(\sqrt{\cdot}\)をとったものです。

先ほどの双曲螺旋よりも、原点に近づいてゆくスピードが遅いことがわかります。これは分母に\(\sqrt{\cdot}\)がついたことで、\(\sqrt{\theta}\)が増加しづらくなった、つまり全体としては\( \frac{a}{\sqrt{\theta}}\)は減少しづらくなった、ということを表しています。

つまり、

  • \(p\)の値が大きいほど、原点に近づくスピードが速い

  • \(p\)の値が小さいほど、原点に近づくスピードが遅い

\(p\)が有理数ならなんでも良いわけで、仮にこれが負の有理数になると、アルキメデスの螺旋になります。実際に\(p=-1\)を代入してプログラムを実行してみましょう。

9. その他の曲線#

上で紹介した曲線以外にも、極方程式を使うと色々な曲線を書くことができます。興味がある人は、以下の例についても考えてみましょう。

9.1. #

極方程式

\[\begin{equation*} r = {(定数)} \end{equation*}\]

は極を中心とするを表します。

円は極からの距離が等しい点の軌跡と見ることができるので、直感的にも、わかりやすいのではないでしょうか。 半径が一定で、角度は任意、そんな図形は確かに円です。

Hide code cell source
# 半径
radius = 2
# 描画の細かさ
stp = 0.1

stp_line = 0.00001
max_range = 2 * np.pi
theta = np.arange(0, max_range, stp_line)
thetas = np.arange(0, max_range, stp)
def f(x):
  return radius
# base figure
X,Y = coordinate(f(theta), theta)
fig, ax = plt.subplots()
ax.set_aspect('equal')

# animation drawing section
artists = []
artist_prev = []
for t in thetas:
  artists.append(draw_steps(ax,artist_prev, f(t), t))

artists.append(draw_finish(ax, artist_prev, X, Y))

ani = matplotlib.animation.ArtistAnimation(fig, artists, interval=500)
html = ani.to_jshtml(default_mode = 'once')
plt.close(fig)
HTML(html)

9.2. レムニスケート#

レムニスケートは

(9.1)#\[\begin{equation} r^2 = a^2 \cos 2\theta \end{equation}\]

で表されます。こう書かれるとどんな図形か全くわからないので、とりあえず描いてみます。

Hide code cell source
a = 1
stp = 0.1

stp_line = 0.00001
max_range = 2 * np.pi
theta = np.arange(0, np.pi / 4, stp_line)
theta = np.concatenate([theta, np.arange(3*np.pi / 4, 5*np.pi/4, stp_line)])
theta = np.concatenate([theta, np.arange(7*np.pi / 4, 2*np.pi, stp_line)])

thetas = np.arange(0, np.pi / 4, stp)
thetas = np.concatenate([thetas, np.arange(3*np.pi / 4, 5*np.pi/4, stp)])
thetas = np.concatenate([thetas, np.arange(7*np.pi / 4, 2*np.pi, stp)])

def f(x):
  return (a **2) * abs(np.cos(2 * x))

# base figure
X,Y = coordinate(f(theta), theta)
fig, ax = plt.subplots()

# animation drawing section
artists = []
artist_prev = []
for t in thetas:
  artists.append(draw_steps(ax,artist_prev, f(t), t))

artists.append(draw_finish(ax, artist_prev, X, Y))

ani = matplotlib.animation.ArtistAnimation(fig, artists, interval=500)
html = ani.to_jshtml(default_mode = 'once')
plt.close(fig)
HTML(html)

9.3. 蜘蛛の巣#

極方程式

\[\begin{equation*} r = a \cos ^2(n\theta) + b \sin ^2 (n\theta) \end{equation*}\]

で表される曲線は蜘蛛の巣になります。

\(a\)\(b\), \(n\)の値を変えてみると、いろいろな形に変化します。

Hide code cell source
a = 10
b = 9

n = 9
# 描画の細かさ
stp = 0.1

# 描画スタートのθ
min_range = 0
# 描画終了のθ
max_range = 2 * np.pi

stp_line = 0.00001
theta = np.arange(min_range, max_range, stp_line)
thetas = np.arange(min_range, max_range, stp)
def f(a, b, x, n):
  return a * (np.cos(n * x) ** 2) + b * (np.sin(n * x) ** 2)

# base figure
X,Y = coordinate(f(a, b, theta, n), theta)

# base figure
X,Y = coordinate(f(a, b, n, theta), theta)
fig, ax = plt.subplots()

# animation drawing section
artists = []
artist_prev = []
for t in thetas:
  artists.append(draw_steps(ax,artist_prev, f(a,b,n,t), t))

artists.append(draw_finish(ax, artist_prev, X, Y))

ani = matplotlib.animation.ArtistAnimation(fig, artists, interval=500)
html = ani.to_jshtml(default_mode = 'once')
plt.close(fig)
HTML(html)

9.4. 二次曲線の極方程式#

二次曲線\(C\)の焦点を極とする極座標において、\(C\)の極方程式は

(9.2)#\[\begin{equation} r=\frac{ae}{1-e\cos \theta} \end{equation}\]

です。ここで\(e\)は離心率と呼ばれ、

  • \(0<e<1 \to\) 楕円

  • \(e=1\to\) 放物線

  • \(e > 1 \to\) 双曲線

になります。

では実際に図で表すとどんな感じになるか見てみましょう。

Caution

\(e\geqq 1\)の時、つまり双曲線、放物線の場合には一部の点が発散してしまうので、\(\frac{\pi}{4}\leqq \theta \leqq \frac{7\pi}{4}\)で表示しています。

以下では、

\[\begin{align*} \begin{cases} a=0.5 & \\ e = 0.8 & \end{cases} \end{align*}\]

で描画しています。

Hide code cell source
# aの値と離心率(いろいろ変更してどのように変化するか見てみよう!)
a = 0.5
e = 0.8

## 描画の細かさ (θの幅指定。細かくしたければここの値を小さくすれば良いです)
stp = 0.1

# 極方程式
def f(x):
  return a / (1 - e * np.cos(x))

stp_line = 0.00001
# 双曲線は発散するから描画範囲を限定している
if e >= 1:
  theta = np.arange(np.pi/4, 7 * np.pi / 4, stp_line)
  thetas = np.arange(np.pi/4, 7 * np.pi / 4, stp)
  r = a / (1 - e * np.cos(theta))
  hyp = 1
else:
  theta = np.arange(0, 2 * np.pi, stp_line)
  thetas = np.arange(0, 2 * np.pi, stp)

# base figure
X,Y = coordinate(f(theta), theta)
fig, ax = plt.subplots()

# animation drawing section
artists = []
artist_prev = []
for t in thetas:
  artists.append(draw_steps(ax,artist_prev, f(t), t))

artists.append(draw_finish(ax, artist_prev, X, Y, '焦点'))

ani = matplotlib.animation.ArtistAnimation(fig, artists, interval=500)
html = ani.to_jshtml(default_mode='once')
# ani.save('quadric.gif')
plt.close(fig)
HTML(html)